using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Soap;
using MsgLogic;
using System.Threading;
using System.Drawing;
using System.ComponentModel;
using System.Net.NetworkInformation;

namespace ServerLogicDll
{
    public class Server
    {
        //public EventHandler<MsgArrivedEventArgs> MsgArrived;
        public event EventHandler<ClientConnectedEventArgs> NewClientConnected;
        public event EventHandler<ClientDisonnectEventArgs> DisconnectClient;

        private TcpListener tcpListener;
        private Thread thread;
        private IPAddress ipAddress;
        private int port;
        private List<ConnectedClient> clientsList;
        

        public IPAddress IpAddress
        {
            get { return ipAddress; }
            set { ipAddress = value; }
        }
        public int Port
        {
            get { return port; }
            set { port = value; }
        }
        public List<ConnectedClient> ClientsList
	    {
            get { return clientsList; }
            set { clientsList = value; }
	    }

        private void GetNewClients()
        {
            try
            {
                //BaseMsg msg;
                while (true)
                {
                    //check the message
                    //msg = (BaseMsg)soapFormatter.Deserialize(networkStream);

                    ConnectedClient client = new ConnectedClient(tcpListener.AcceptTcpClient());
                    client.MsgArrived += new EventHandler<MsgArrivedEventArgs>(client_MsgArrived);
                    client.DisconnectClient += new EventHandler<ClientDisonnectEventArgs>(client_DisconnectClient);
                    //clientsList.Add(client);
                }
            }
            catch (Exception)
            {

            }
           
        }

        void client_DisconnectClient(object sender, ClientDisonnectEventArgs e)
        {
            OnClientDisconnect(e.UserName);
        }

        void client_MsgArrived(object sender, MsgArrivedEventArgs e)
        {
            if (e.Msg as StartMsg != null)
            {
                (sender as ConnectedClient).UserName = e.Msg.UserName;
                clientsList.Add(sender as ConnectedClient);
                TextMsg txt = new TextMsg("server", e.Msg.UserName + " has just connected", Color.Black);
                SendAllClients(txt);
                //raise event
                OnNewClientConnected(e.Msg.UserName);

                ////timer part
                //t = new System.Timers.Timer(10000);
                //t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
            }
            else if (e.Msg as DisconnectMsg != null)
            {
                (sender as ConnectedClient).UserName = e.Msg.UserName;
                clientsList.Remove(sender as ConnectedClient);
                RemoveClient(sender as ConnectedClient);
                (sender as ConnectedClient).MsgArrived -= new EventHandler<MsgArrivedEventArgs>(client_MsgArrived);
                (sender as ConnectedClient).DisconnectClient -= new EventHandler<ClientDisonnectEventArgs>(client_DisconnectClient);
                TextMsg txt = new TextMsg("server", e.Msg.UserName + " disconnected", Color.Black);
                SendAllClients(txt);
                //raise event
                OnClientDisconnect(e.Msg.UserName);
            }
            else //if (e.Msg as InfoMsg != null)
            {
                //TODO: info msg
                SendAllClients(e.Msg);
            }
            
        }

        //void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        //{
        //    Ping p = new Ping();
        //    PingReply pr = p.Send(
        //}

        public void StartListen()
        {
            tcpListener.Start();
            InitializeThread();
            thread.Start();
        }
        public void StartListen(BackgroundWorker worker)
        {
            tcpListener.Start();
            //InitializeThread();
            //thread.Start();
            //worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerAsync();
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            GetNewClients();
        }
        public void StopListen()
        {
            DisconnectMsg msg = new DisconnectMsg("Server");
            SendAllClients(msg);
            tcpListener.Stop();
            clientsList.Clear();
            //thread.Abort();
            
        }
        public void SendAllClients(BaseMsg msg)
        {
            foreach (ConnectedClient cl in clientsList)
            {
                cl.SendMsg(msg);
            }
        }
        private void RemoveAllClients()
        {
            foreach (ConnectedClient cl in clientsList)
            {
                RemoveClient(cl);
            }
        }
        //private void AddNewClient(ConnectedClient client)
        //{

        //}
        //public void AddNewClient(ConnectedClient client)
        //{

        //}
        private void RemoveClient(ConnectedClient client)
        {
            client.RemoveClient();
        }
        public void RemoveClient(string userName)
        {
            for (int i = 0; i < clientsList.Count; i++)
            {
                if (clientsList[i].UserName == userName)
                {
                    RemoveClient(clientsList[i]);
                    clientsList.RemoveAt(i);
                }
            }
            //foreach (ConnectedClient client in clientsList)
            //{
            //    if (client.UserName == userName)
            //    {
            //        RemoveClient(client);
            //        clientsList.Remove(client);
            //    }
            //}
        }

        public Server(IPAddress ipAddress, int port)
        {
            this.ipAddress = ipAddress;
            this.port = port;
            clientsList = new List<ConnectedClient>();
            tcpListener = new TcpListener(ipAddress, port);
            
            //start listen
            //StartListen();
            //thread.Start();
        }
        private void InitializeThread()
        {
            ThreadStart ts = new ThreadStart(GetNewClients);
            thread = new Thread(ts);
            thread.IsBackground = true;
        }
        public void OnNewClientConnected(string userName)
        {
            if (NewClientConnected != null)
                NewClientConnected(this, new ClientConnectedEventArgs(userName));
        }
        public void OnClientDisconnect(string userName)
        {
            //client disconnection code here:
            RemoveClient(userName);

            if (DisconnectClient != null)
                DisconnectClient(this, new ClientDisonnectEventArgs(userName));
        }




    }
}
